﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NEmu;
using NEmu.MemoryPages;
using Super64.Core.Memory.Ram.MemoryPages;
using Super64.Core.Memory.Ram.Registers;
using System.Runtime.InteropServices;

/*0x0000 0000 to 0x03EF FFFF RDRAM Memory
 0x03F0 0000 to 0x03FF FFFF RDRAM Registers
 0x0400 0000 to 0x040F FFFF SP Registers
 0x0410 0000 to 0x041F FFFF DP Command Registers
 0x0420 0000 to 0x042F FFFF DP Span Registers
 0x0430 0000 to 0x043F FFFF MIPS Interface (MI) Registers
 0x0440 0000 to 0x044F FFFF Video Interface (VI) Registers
 0x0450 0000 to 0x045F FFFF Audio Interface (AI) Registers
 0x0460 0000 to 0x046F FFFF Peripheral Interface (PI) Registers
 0x0470 0000 to 0x047F FFFF RDRAM Interface (RI) Registers
 0x0480 0000 to 0x048F FFFF Serial Interface (SI) Registers
 0x0490 0000 to 0x04FF FFFF Unused
 0x0500 0000 to 0x05FF FFFF Cartridge Domain 2 Address 1
 0x0600 0000 to 0x07FF FFFF Cartridge Domain 1 Address 1
 0x0800 0000 to 0x0FFF FFFF Cartridge Domain 2 Address 2
 0x1000 0000 to 0x1FBF FFFF Cartridge Domain 1 Address 2
 0x1FC0 0000 to 0x1FC0 07BF PIF Boot ROM
 0x1FC0 07C0 to 0x1FC0 07FF PIF RAM
 0x1FC0 0800 to 0x1FCF FFFF Reserved
 0x1FD0 0000 to 0x7FFF FFFF Cartridge Domain 1 Address 3
 0x8000 0000 to 0xFFFF FFFF External SysAD Device*/

namespace Super64.Core.Memory.Ram
{
    [Serializable]
    public sealed class N64Memory : NEmu.Memory
    {
        // Registers Pointers
        IntPtr m_RDRAMRegs = IntPtr.Zero;
        IntPtr m_SPRegs = IntPtr.Zero;
        IntPtr m_DPCmdRegs = IntPtr.Zero;

        public N64Memory(N64Machine parentMachine): base(parentMachine)
        {
        }

        protected override void AllocatePages()
        {
            AllocateUnsafeMemoryResources();
            AddPage(new RDRAMMemoryPage());
            AddPage(new StructMemoryPage<RDRAMRegisters>(m_RDRAMRegs));
            AddPage(new StructMemoryPage<SPRegisters>(m_SPRegs));
            AddPage(new StructMemoryPage<DPCommandRegisters>(m_DPCmdRegs));
        }

        private unsafe void AllocateUnsafeMemoryResources()
        {
            m_RDRAMRegs = Tools.AllocateUnmanagedStructure<RDRAMRegisters>();
            m_SPRegs = Tools.AllocateUnmanagedStructure<SPRegisters>();
            m_DPCmdRegs = Tools.AllocateUnmanagedStructure<DPCommandRegisters>();

        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            Marshal.FreeCoTaskMem(m_RDRAMRegs);
            Marshal.FreeCoTaskMem(m_SPRegs);
            Marshal.FreeCoTaskMem(m_DPCmdRegs);
        }

        public unsafe RDRAMRegisters* RDRAMRegs
        {
            get { return (RDRAMRegisters*)m_RDRAMRegs; }
        }

        public unsafe SPRegisters* SPRegs
        {
            get { return (SPRegisters*)m_SPRegs; }
        }

        public unsafe DPCommandRegisters* DPCommandRegs
        {
            get { return (DPCommandRegisters*)m_DPCmdRegs; }
        }
    }
}
